////////////////////////////////
//
// DUST ACCUMULATION CLOSURE
// SOURCE FILE
//
////////////////////////////////
 
// The following allows us to use the fmath, genclosure, kernel_types,
// kernel montecarlo, and bsdf_diffuse_ramp headers.
 
#include <OpenImageIO/fmath.h>
 
#include <OSL/genclosure.h>
 
// This is the header that stores the base class for the closure. (CBSDFClosure)
// It also is where 'CLOSURE_PREPARE()' is defined.
#include "osl_closures.h"
 
#include "kernel_types.h"
#include "kernel_montecarlo.h"
#include "closure/bsdf_dust_accumulation.h"
 
// The following line opens the code, kind of like the {} enclose the main function in C.
CCL_NAMESPACE_BEGIN
 
using namespace OSL;
 
class DustAccumulationClosure : public CBSDFClosure {
public:
        DustAccumulationClosure() : CBSDFClosure(LABEL_DIFFUSE) {}
        Color3 color;
        float3 fcolor;

        DustAccumulationClosure() : CBSDFClosure(LABEL_GLOSSY)
        {}
 
        // This is where the Closure is named.
        const char *name() const { return "dust_accumulation"; }
 
        void setup()
        {
            sc.prim = this;
            m_shaderdata_flag = bsdf_phong_ramp_setup(&sc);

            fcolor = TO_FLOAT3(color);
        }
       
        // Defines the blur, using functions from the header.
        void blur(float roughness)
        {
                bsdf_dust_accumulation_blur(&sc, roughness);
        }
       
        // Defines the reflection, using a function from the header.
        float3 eval_reflect(const float3 &omega_out, const float3 &omega_in, float& pdf) const
        {
                return dust_accumulation_eval_reflect(&sc, fcolor, omega_out, omega_in, &pdf);
        }
 
        // Defines the transmission, using a function from the header.
        float3 eval_transmit(const float3 &omega_out, const float3 &omega_in, float& pdf) const
        {
                return dust_accumulation_eval_transmit(&sc, fcolor, omega_out, omega_in, &pdf);
        }
 
 
       // Although this sampling excerpt looks complicated, all of the work is done in the
       // header file, so just keep the inputs the same, and replace only the name of the
       // function to correspond to what you have in the header.
 
        int sample(const float3 &Ng,
                   const float3 &omega_out, const float3 &domega_out_dx, const float3 &domega_out_dy,
                   float randu, float randv,
                   float3 &omega_in, float3 &domega_in_dx, float3 &domega_in_dy,
                   float &pdf, float3 &eval) const
        {
                return bsdf_dust_accumulation_phong_ramp_sample(&sc, fcolors, Ng, omega_out, domega_out_dx, domega_out_dy,
                        randu, randv, &eval, &omega_in, &domega_in_dx, &domega_in_dy, &pdf);
        }
};
 
// The following block of code is where you define your inputs and your outputs.
// In this example it is a static array called ClosureParam which is of the type 'params'.
// A function is used to define each element, there is one function for each type of data.
// The 'CLOSURE_FINISH_PARAM()' is used to define the output closure.
 
ClosureParam *closure_bsdf_dust_accumulation_params()
{
        static ClosureParam params[] = {
			    // float g, float dRad, float sRad, float thickness
                CLOSURE_FLOAT3_PARAM(DustAccumulationClosure, sc.N),
                CLOSURE_FLOAT_PARAM(DustAccumulationClosure, sc.data0),
				CLOSURE_FLOAT_PARAM(DustAccumulationClosure, g),
				CLOSURE_FLOAT_PARAM(DustAccumulationClosure, thickness),
                CLOSURE_COLOR_ARRAY_PARAM(DustAccumulationClosure, colors, 8),
                CLOSURE_STRING_KEYPARAM("label"),
            CLOSURE_FINISH_PARAM(DustAccumulationClosure)
        };
        return params;
}

CCLOSURE_PREPARE(closure_bsdf_dust_accumulation_prepare, DustAccumulation)

CCL_NAMESPACE_END
